package com.qinglei.recoup.system.service.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qinglei.recoup.common.domain.CommonRes;
import com.qinglei.recoup.common.tenant.TenantContextHolder;
import com.qinglei.recoup.common.utils.RecoupUtil;
import com.qinglei.recoup.system.dao.EventMapper;
import com.qinglei.recoup.system.domain.Bed;
import com.qinglei.recoup.system.domain.DictBO;
import com.qinglei.recoup.system.domain.Event;
import com.qinglei.recoup.system.domain.EventBedBO;
import com.qinglei.recoup.system.domain.EventProc;
import com.qinglei.recoup.system.domain.User;
import com.qinglei.recoup.system.enums.EventEnum;
import com.qinglei.recoup.system.manager.DictManager;
import com.qinglei.recoup.system.pojo.EventProcParam;
import com.qinglei.recoup.system.pojo.EventProcReportParam;
import com.qinglei.recoup.system.pojo.KeyValueVO;
import com.qinglei.recoup.system.service.BedService;
import com.qinglei.recoup.system.service.EventLogService;
import com.qinglei.recoup.system.service.EventProcService;
import com.qinglei.recoup.system.service.EventService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.List;

/**
 * @author syp
 */
@Service
@Slf4j
public class EventServiceImpl extends ServiceImpl<EventMapper, Event> implements EventService {

    public static final String DICT_EVENT_FILTER_TYPE = "event_filter_type";
    public static final String DICT_REPORT_REASON = "report_reason";

    /**
     * 在线巡查
     */
    public static final int EVENT_FILTER_TYPE_TOUR = 3;
    /**
     * 交接班记录
     */
    public static final int EVENT_FILTER_TYPE_CHANGE_SHIFTS = 4;
    @Resource
    private DictManager dictManager;

    @Resource
    private EventProcService eventProcService;

    @Resource
    private BedService bedService;

    @Resource
    @Lazy
    private EventLogService eventLogService;

    /**
     * 获取现场状况选项列表
     *
     * @return
     */
    @Override
    public List<KeyValueVO> getSiteOptionList() {
        List<DictBO> listDict = dictManager.getDictItemList(DICT_REPORT_REASON);
        List<KeyValueVO> listOption = new ArrayList<>();
        if (CollectionUtils.isEmpty(listDict)) {
            return listOption;
        }
        listDict.forEach(dict -> {
            KeyValueVO keyValueVO = new KeyValueVO();
            keyValueVO.setKey(dict.getKeyy());
            keyValueVO.setValue(dict.getValuee());
            listOption.add(keyValueVO);
        });
        return listOption;
    }

    /**
     * 获取事件筛选选项列表
     *
     * @return
     */
    @Override
    public List<KeyValueVO> getEventFilterOption(Integer onlyBed) {
        List<DictBO> listDict = dictManager.getDictItemList(DICT_EVENT_FILTER_TYPE);
        List<KeyValueVO> listOption = new ArrayList<>();
        if (CollectionUtils.isEmpty(listDict)) {
            return listOption;
        }
        listDict.forEach(dict -> {
            if (onlyBed != null && onlyBed == 1) {
                if (dict.getKeyy() == EVENT_FILTER_TYPE_TOUR || dict.getKeyy() == EVENT_FILTER_TYPE_CHANGE_SHIFTS) {
                    return;
                }
            }
            KeyValueVO keyValueVO = new KeyValueVO();
            keyValueVO.setKey(dict.getKeyy());
            keyValueVO.setValue(dict.getValuee());
            listOption.add(keyValueVO);
        });
        return listOption;
    }

    /**
     * 护工首页页面 接单报警事件（报警时点击处理接口）
     *
     * @param param
     * @return
     */
    @Override
    public CommonRes takeEvent(EventProcParam param) {
        List<EventProc> eventProcs = eventProcService.getBaseMapper().selectList(Wrappers.<EventProc>lambdaQuery()
                .eq(EventProc::getEventId, param.getEventId()).eq(EventProc::getStatus, 1).orderByDesc(EventProc::getCreateTime));
        if (eventProcs.size() < 1) {
            return CommonRes.failed("报警已经有人去处理");
        }

        EventProc eventProc = eventProcs.get(0);
        eventProc.setStatus(2);
        User currentUser = RecoupUtil.getCurrentUser();
        eventProc.setTakeUserId(currentUser.getId());
        eventProc.setTakeTime(LocalDateTime.now());
        //
        long nowSecond = eventProc.getTakeTime().toEpochSecond(ZoneOffset.of("+8"));
        long endSecond = eventProc.getHappenTime().toEpochSecond(ZoneOffset.of("+8"));
        long absSeconds = Math.abs(nowSecond - endSecond);
        eventProc.setWaitTime(Integer.parseInt(String.valueOf(absSeconds)));
        int count = eventProcService.getBaseMapper().updateById(eventProc);
        if (count > 0) {
            Integer tenantId = TenantContextHolder.getTenantId();
            // 清除待接单缓存
            EventBedBO eventBedBO = new EventBedBO(param.getEventId(), param.getBedId(), tenantId);
            bedService.delWaitTakeEventCache(eventBedBO);
            // 记录事件日志并推送消息
            eventLogService.procEventLog(param.getBedId(), eventProc.getTakeUserId(), param.getEventId(),
                    EventEnum.EVENT_PROC_TAKE.getCode(), null, eventProc.getTenantId());
            eventLogService.procEventLog(param.getBedId(), null, param.getEventId(),
                    EventEnum.EVENT_PROC_PROCESSING.getCode(), null, eventProc.getTenantId());
            // 推送床位当前状态消息
            bedService.pushBedCurStatus(param.getBedId());
            return CommonRes.ok();
        }
        return CommonRes.failed();
    }

    /**
     * 护工首页页面 提交处置记录
     *
     * @param param
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public CommonRes submitReport(EventProcReportParam param) {
        List<EventProc> eventProcs = eventProcService.getBaseMapper().selectList(Wrappers.<EventProc>lambdaQuery()
                .eq(EventProc::getEventId, param.getEventId())
                .eq(EventProc::getStatus, 2)
                .orderByDesc(EventProc::getCreateTime));
        if (eventProcs.size() < 1) {
            return CommonRes.failed("已经提交过处置报告");
        }
        EventProc eventProc = eventProcs.get(0);
        eventProc.setStatus(3);
        User currentUser = RecoupUtil.getCurrentUser();
        eventProc.setFinishUserId(currentUser.getId());
        eventProc.setFinishTime(LocalDateTime.now());
        //
        long nowSecond = eventProc.getFinishTime().toEpochSecond(ZoneOffset.of("+8"));
        long endSecond = eventProc.getTakeTime().toEpochSecond(ZoneOffset.of("+8"));
        long absSeconds = Math.abs(nowSecond - endSecond);
        eventProc.setProcTime((int) absSeconds);
        eventProc.setProcReport(param.getProcReport());
        eventProc.setSiteOption(param.getSiteOption());
        int count = eventProcService.getBaseMapper().updateById(eventProc);
        if (count > 0) {
            Bed bed = new Bed();
            bed.setId(param.getBedId());
            bed.setEventId(0L);
            bed.setStatus(Bed.STATUS_NORMAL);
            bed.setSubStatus(Bed.SUB_STATUS_CLEAR);
            bed.setHappenTime(null);
            int count1 = bedService.getBaseMapper().updateById(bed);
            if (count1 > 0) {
                // 记录事件日志并推送消息
                String content = "";
                if (eventProc.getSiteOption() == EventProc.OPTION_OTHER) {
                    content = eventProc.getProcReport();
                } else {
                    DictBO dictItem = dictManager.getDictItem(DICT_REPORT_REASON, (long) eventProc.getSiteOption());
                    content = dictItem.getValuee();
                }
                // 记录事件日志并推送消息
                eventLogService.procEventLog(param.getBedId(), eventProc.getFinishUserId(), param.getEventId(),
                        EventEnum.EVENT_PROC_FINISH.getCode(), content, eventProc.getTenantId());
                // 推送床位当前状态消息
                bedService.pushBedCurStatus(param.getBedId());

                return CommonRes.ok();
            } else {
                throw new RuntimeException("提交处置记录失败, param:" + param);
            }
        }
        return CommonRes.failed("提交处置记录失败");
    }

}
